package com.app.brilliant.game.controller;
import com.app.brilliant.common.api.ApiResult;
import com.app.brilliant.common.controller.BaseController;
import com.app.brilliant.game.bean.*;
import com.app.brilliant.game.dto.BriClassHourDetailDTO;
import com.app.brilliant.game.dto.WeekCompletionDTO;
import com.app.brilliant.game.response.BriClassHourWithNextInfo;
import com.app.brilliant.game.response.BriClassHourWithTypeInfo;
import com.app.brilliant.game.response.BriClassificationCourseInfo;
import com.app.brilliant.game.response.BriCourseWithCompletionInfo;
import com.app.brilliant.game.service.*;
import com.app.brilliant.game.vo.UserRankData;
import com.app.brilliant.shiro.util.LoginUtil;
import com.app.brilliant.sign.constant.Constants;
import com.app.brilliant.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.*;

@RestController
@RequestMapping("/dev")
public class DevCourseController extends BaseController {
    @Autowired
    private BriClassificationService briClassificationService;
    @Autowired
    private BriClassHourService briClassHourService;
    @Autowired
    private BriCourseService briCourseService;
    @Autowired
    private WxConfigService wxConfigService;
    @Autowired
    private BriUserExpInfoService briUserExpInfoService;
    @Autowired
    private BriUserHourCompleteService briUserHourCompleteService;
    @Autowired
    private BriUserPlanService briUserPlanService;
    @Autowired
    private BriPlanService briPlanService;
    @Autowired
    private BriOrderService briOrderService;
    @Autowired
    private WxPayService wxPayService;
    @RequestMapping("/getCourses")
    public ApiResult<List<BriClassificationCourseInfo>> getCourses() {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        List<BriClassificationCourseInfo> list = briClassificationService.selectClassificationWithCourses(userId.intValue());
        return ApiResult.ok(list);
    }
    @RequestMapping("/getCourseDetail")
    public ApiResult<Map<String, Object>> getClassHourDetailsByCourseId(@RequestParam Long courseId) {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        List<BriClassHourWithTypeInfo> list = briClassHourService.getClassHourDetailsByCourseId(courseId, userId.intValue());
        BriCourseWithCompletionInfo courseWithCompletionInfo = briCourseService.getCourseWithCompletionInfo(courseId, userId.intValue());
        Map<String,Object> result = new HashMap<>();
        result.put("course", courseWithCompletionInfo);
        result.put("classHourList", list);
        return ApiResult.ok(result);
    }
    
    @RequestMapping("/getUserRank")
    public ApiResult<UserRankData> getUserRank(@RequestParam(defaultValue = "30") Integer limit) {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        UserRankData result = briUserExpInfoService.getUserRank(limit, userId);
        return ApiResult.ok(result);
    }

    @RequestMapping("/getTopCompletionClassHours")
    public ApiResult<List<BriClassHourWithNextInfo>> getTopCompletionClassHours() {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        String domain = wxConfigService.getConfigValue(Constants.NomalConfigKey.PictureDomain);
        List<BriClassHourWithNextInfo> result = briClassHourService.getTopCompletionClassHours(userId.intValue(),5);
        result.forEach(v->{
            Integer id = v.getId();
            BriClassHour briClassHour = briClassHourService.getUnCompleteNextClassHour(id);
            if(briClassHour != null){
                v.setNextClassHourId(briClassHour.getId().longValue());
                v.setNextClassHourName(briClassHour.getName());
            }
            v.setCurrentCourseIcon(domain + v.getCurrentCourseIcon());
        });
        return ApiResult.ok(result);
    }
    
    @RequestMapping("/uploadClassComplete")
    public ApiResult<Boolean> uploadClassComplete(@RequestParam Integer classHourId) {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        boolean result = briUserHourCompleteService.completeClassHour(classHourId, userId.intValue());
        return ApiResult.ok(result);
    }

    @GetMapping("/weekCompletionRecords")
    public ApiResult<List<WeekCompletionDTO>> getWeekCompletionRecords() {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        List<WeekCompletionDTO> records = new ArrayList<>();
        LocalDate today = LocalDate.now();
        // 获取最近一周的日期（从周一到周日）
        LocalDate startOfWeek = today.with(DayOfWeek.MONDAY);
        for (int i = 0; i < 7; i++) {
            LocalDate date = startOfWeek.plusDays(i);
            WeekCompletionDTO dto = new WeekCompletionDTO();
            dto.setWeekDay(date.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.CHINA));
            dto.setDay(date.getDayOfMonth());
            dto.setCompleted(briUserHourCompleteService.hasCompletionRecordOnDate(date, userId.intValue()));
            records.add(dto);
        }
        return ApiResult.ok(records);
    }

    @RequestMapping("/generateWxPayQrCode")
    public ApiResult<String> generateWxPayQrCode(@RequestParam Long planId) {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        
        // 1. 检查用户订阅状态
        BriUserPlan userPlan = briUserPlanService.getByUserId(userId);
        LocalDateTime localDateTime = new Timestamp(userPlan.getEndTime().getTime())
                .toLocalDateTime();
        if (userPlan != null && userPlan.getPlanId().equals(planId) && localDateTime.isAfter(LocalDateTime.now())) {
            return ApiResult.fail("您已订阅该计划，无需重复订阅");
        }

        // 2. 查询计划金额并生成订单
        BriPlan plan = briPlanService.getById(planId);
        if (plan == null) {
            return ApiResult.fail("订阅计划不存在");
        }

        BriOrder order = new BriOrder();
        order.setUid(userId.intValue());
        order.setOrderNumber(UUID.randomUUID().toString().replaceAll("\\-",""));
        order.setGoodsId(planId.intValue());
        order.setMoney(plan.getMoney());
        order.setStatus(0); // 未支付
        order.setCreateTime(new Date());
        briOrderService.save(order);

        // 3. 调用微信支付接口生成二维码
        try {
            String qrCodeUrl = wxPayService.generateNativePayQrCode(
                order.getOrderNumber(),
                plan.getMoney(),
                "订阅计划-" + plan.getName()
            );
            return ApiResult.ok(qrCodeUrl);
        } catch (Exception e) {
            return ApiResult.fail("生成支付二维码失败");
        }
    }

    @RequestMapping("/wxPayNotify")
    public String wxPayNotify(HttpServletRequest request) {
        Map<String, String> params = wxPayService.parseRequest(request);
        // 验证签名和支付状态
        if (!wxPayService.verifySign(params)) {
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }
        String orderId = params.get("out_trade_no");
        BriOrder order = briOrderService.getById(orderId);
        if (order == null || order.getStatus() != 0) {
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }
        // 更新订单状态
        order.setStatus(1); // 已支付
        order.setPayTime(new Date());
        briOrderService.updateById(order);
        // 更新用户订阅信息
        BriUserPlan userPlan = briUserPlanService.getByUserId(order.getUid().longValue());
        if (userPlan == null) {
            userPlan = new BriUserPlan();
            userPlan.setUid(order.getUid());
        }
        userPlan.setPlanId(order.getGoodsId());
        userPlan.setStartTime(new Date());
        BriPlan briPlan = briPlanService.getById(order.getGoodsId());
        Date date = DateUtil.getEndTime(briPlan.getType());
        userPlan.setEndTime(date); // 假设订阅时长为1个月
        briUserPlanService.saveOrUpdate(userPlan);

        return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
    }

    @RequestMapping("/getSubscriptionStatus")
    public ApiResult<Map<String, Object>> getSubscriptionStatus() {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        BriUserPlan userPlan = briUserPlanService.getByUserId(userId);
        Map<String, Object> result = new HashMap<>();
        if (userPlan != null) {
            BriPlan plan = briPlanService.getById(userPlan.getPlanId());
            result.put("planName", plan.getName());
            result.put("startTime", userPlan.getStartTime());
            result.put("endTime", userPlan.getEndTime());
            result.put("isActive", userPlan.getEndTime().after(new Date()));
        } else {
            result.put("isActive", false);
        }
        return ApiResult.ok(result);
    }

    @RequestMapping("/getOrderInfo")
    public ApiResult<BriOrder> getOrderInfo(@RequestParam String orderNumber) {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        BriOrder order = briOrderService.getByOrderNumberAndUserId(orderNumber, userId);
        if (order == null) {
            return ApiResult.fail("订单不存在或不属于当前用户");
        }
        return ApiResult.ok(order);
    }

    @GetMapping("/briClassHourDetail")
    public ApiResult<BriClassHourDetailDTO> getBriClassHourDetail(
        @RequestParam Long id
    ) {
        Long userId = LoginUtil.getLoginDevUserRedisVoId();
        // 2. 查询briClassHour详情
        BriClassHour briClassHour = briClassHourService.getById(id);
        if (briClassHour == null) {
            return ApiResult.fail("课程不存在");
        }
        BriUserHourComplete briUserHourComplete = briUserHourCompleteService.getByUserIdAndClassHourId(userId.intValue(), briClassHour.getId());
        // 3. 获取用户订阅信息
        BriUserPlan userPlan = briUserPlanService.getByUserId(userId);
        boolean isUnlocked = userPlan != null && userPlan.getEndTime().after(new Date());
        // 5. 封装返回结果
        BriClassHourDetailDTO detailDTO = new BriClassHourDetailDTO();
        detailDTO.setExp(briClassHour.getExp());
        detailDTO.setCompleted(briUserHourComplete.getComplete() == 1);
        detailDTO.setLocked(briClassHour.getLocked());
        detailDTO.setCurrent(isUnlocked);
        return ApiResult.ok(detailDTO);
    }
}
